﻿using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using wRPCclient;
using wRPC;
using static wRPCclient.ClientChannel;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using wRPCService;

namespace gateway
{
    public class CallServer
    {
        static ConcurrentDictionary<string, ClientChannelQueue> _serviceDic = new ConcurrentDictionary<string, ClientChannelQueue>();
        public static Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
        public static void heartbeat()
        {

            //  System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(keep),null);
        }
        public static bool distributed = false;
        public static string CallService(server ser, String rt, String rls, object[] objs,
            Dictionary<string, String> Headers, Dictionary<string, String> keysCookies, ClientChannel.recdata rec = null, ClientChannel.recdataStream recStream = null,
            wRPCclient.filedata fd = null)
        {
            bool locked = false;
            wRPCclient.ClientChannel clientChannel = null;

            ClientChannelQueue CCQ = null;

            try
            {
                if (distributed)
                {

                    clientChannel = new wRPCclient.ClientChannel(ser.IP, ser.Port);
                    CCQ = new ClientChannelQueue();
                    CCQ.clientChannel = clientChannel;
                    clientChannel.Headers = Headers;
                    clientChannel.Cookies = keysCookies;

                    if (fd != null)
                    {
                        clientChannel.Filedata = fd;

                    }
                    clientChannel.recs = rec;
                    clientChannel.recsStream = recStream;
                    var data = clientChannel.Call<object>(rt, rls, objs);

                    return Newtonsoft.Json.JsonConvert.SerializeObject(data);

                }
                else
                {
                    //单机运行
                    if (!keyValuePairs.ContainsKey(rt))
                    {

                        return JsonConvert.SerializeObject(new { code = 503, msg = "server Route error" });

                    }
                    object obj = keyValuePairs[rt];
                    Type t = obj.GetType();
                    obj = t.Assembly.CreateInstance(t.FullName);
                    MethodInfo mi = t.GetMethod(rls);
                    if (mi != null)
                    {
                        InstallFunAttribute myattribute = (InstallFunAttribute)Attribute.GetCustomAttribute(mi, typeof(InstallFunAttribute));
                        if (myattribute != null)
                        {

                            if (obj is FunctionBase)
                            {
                                (obj as FunctionBase).P2Server = null;
                                (obj as FunctionBase).soc = null;
                            }
                            if (obj is FunctionBase && Headers != null)
                            {


                                (obj as FunctionBase).Headers = Headers;


                            }
                            if (obj is FunctionBase && keysCookies != null)
                            {



                                (obj as FunctionBase).Cookies = keysCookies;

                            }
                            if (obj is FunctionBase && fd != null)
                            {
                                wRPC.filedata ffd = new wRPC.filedata();
                                ffd.data = fd.data;
                                ffd.filename = fd.filename;
                                ffd.filetype = fd.filetype;
                                (obj as FunctionBase).Filedata = ffd;

                            }
                            ParameterInfo[] paramsInfo = mi.GetParameters();//得到指定方法的参数列表 
                            if (paramsInfo.Length != objs.Length)
                            {
                                return JsonConvert.SerializeObject(new { code = 503, msg = "参数不正确" });
                            }
                            for (int i = 0; i < objs.Length; i++)
                            {

                                Type tType = paramsInfo[i].ParameterType;

                                //如果它是值类型,或者String   

                                if (tType.Equals(typeof(string)) || (!tType.IsInterface && !tType.IsClass))

                                {

                                    //改变参数类型   
                                    //HttpUtility.UrlDecode
                                    objs[i] = (Convert.ChangeType(objs[i], tType));

                                }
                                else if (tType.Equals(typeof(byte)) || tType.Equals(typeof(byte[])) || (!tType.IsInterface && !tType.IsClass))
                                {
                                    objs[i] = Convert.FromBase64String(objs[i].ToString());
                                }
                                else if (tType.IsClass)//如果是类,将它的json字符串转换成对象   

                                {

                                    objs[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(objs[i].ToString(), tType);

                                }

                            }
                            //调用API方法，同步或异步的处理放到了AOP内部
                            object rpcdata = Aop.Invoke(mi, obj, objs);
                            return rpcdata is null ? string.Empty : JsonConvert.SerializeObject(rpcdata);
                            //DateTime dt2 = DateTime.Now;
                            //Console.WriteLine("service:" + (dt2 - P2Server.dt).TotalMilliseconds);


                        }
                    }
                }
            }
            catch (Exception e)
            {
                //if (!CCQ.clientChannel.connection())
                //{

                //}
                // _serviceDic.TryRemove(ser.IP + ":" + ser.Port, out CCQ);
                Console.WriteLine(e.StackTrace);
                return JsonConvert.SerializeObject(new { code = 503, msg = "服务器错误" });
            }
            finally
            {
                if (clientChannel != null)
                    clientChannel.Dispose();

            }

            return JsonConvert.SerializeObject(new { code = 503, msg = "服务器错误" });
        }


    }
    public class ClientChannelQueue
    {
        public ClientChannel clientChannel;
        public SpinLock _spinLock = new SpinLock();
    }
}
